package evaluation;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Evaluation {
	public static void main(String args[]){
		new Evaluation().RunEvaluation();
	}
	private String positive_pair_file; // filtered positive_pair_file from Main.java step
	private String base_pair_file; // filtered base_pair file from Main.java step
	private String idiom_file = "evaluation_idioms.txt";
	private String cui_list_file = "evaluation_CUIs.txt";
	private String test_collection_file = "WSD_Test_Collection_cold.txt";
	private String cluster_file = "final_post_cluster_file"; // output of the post-clusters
	public void RunEvaluation(){
		GetArticles_Cluster_Index(cluster_file);
		System.out.println("Results based on filtered positive and base pairs: ");
		int count1[] = GetCountfromPairs(positive_pair_file, true);
		int count2[] = GetCountfromPairs(base_pair_file, false);
		GetEvaluationResult(count1[0],count1[1], count2[0],count2[1]);
		System.out.println("-----------------------------------------------------------");
		System.out.println("Results based on the idiom list");
		int count3[] = GetCountfromClusters(idiom_file);
		GetEvaluationResult(count3[0],count3[1], count3[2], count3[3]);
		System.out.println("-----------------------------------------------------------");
		System.out.println("Results based on the cui list");
		count3 = GetCountfromClusters(cui_list_file);
		GetEvaluationResult(count3[0],count3[1], count3[2], count3[3]);
		System.out.println("-----------------------------------------------------------");
		System.out.println("Results based on the test collections");
		count3 = GetCountfromClusters(test_collection_file);
		GetEvaluationResult(count3[0],count3[1], count3[2], count3[3]);
		System.out.println("-----------------------------------------------------------");
	}
	private HashMap<String,Integer> articles_clusterIndex;
	public void GetArticles_Cluster_Index(String filename){
		articles_clusterIndex = new HashMap<String,Integer>();
		File f=new File(filename);
		FileInputStream fis;
		try {
			fis = new FileInputStream(f);
			InputStreamReader isr=new InputStreamReader(fis);
			BufferedReader br=new BufferedReader(isr);
			String line = br.readLine();
			int count = 0;
			while(line != null){
				line = line.trim();
				if(line.length()>0){
					String ids[] = line.split("\t"); 
					for(int i=1; i<ids.length; i++)
						articles_clusterIndex.put(ids[i], count);
					count++;
				}
				line = br.readLine();
			}
			br.close();
		}catch(IOException e)
		{
			e.printStackTrace();
		}
	}
	public void GetEvaluationResult(int TP, int FN, int TN, int FP){
		int N = TP+TN+FP+FN;
		double precision_p = (double)TP/((double)(TP+FP));
		double recall_p = (double) TP / ((double)(TP+FN));
		double precision_n = (double)TN / ((double)(TN+FN));
		double recall_n = (double)TN / ((double)(TN+FP));
		double FMeasure_p = 2*precision_p*recall_p / (precision_p+recall_p);
		double FMeasure_n = 2*precision_n*recall_n / (precision_n+recall_n);
		double FMeasure = (double)(TP+FN)/((double)N)*FMeasure_p + ((double)(TN+FP))/N*FMeasure_n;
		double Accuracy = ((double)(TP+TN))/N;
		System.out.println("Precision_p: "+ precision_p);
		System.out.println("Recall_p: "+ recall_p);
		System.out.println("----------------------------------------------");
		System.out.println("Precision_n: "+ precision_n);
		System.out.println("Recall_n: "+ recall_n);
		System.out.println("----------------------------------------------");
		System.out.println("F-Measure: "+FMeasure);
		System.out.println("Accuracy: "+Accuracy);
	}
	public int[] GetCountfromPairs(String filename, boolean Positive){
		int count[] = new int[2];
		File f=new File(filename);
		FileInputStream fis;
		try {
			fis = new FileInputStream(f);
			InputStreamReader isr=new InputStreamReader(fis);
			BufferedReader br=new BufferedReader(isr);
			String line = br.readLine();
			while(line != null){
				line = line.trim();
				if(line.length()>0){
					String ids[] = line.split("\t");
					if(ids.length!=2)
						throw new Exception(line+" is not a pair!");
					if(!articles_clusterIndex.containsKey(ids[0]) || !articles_clusterIndex.containsKey(ids[1])){
						line = br.readLine();
						continue;
					}
					int cluster_index1 = articles_clusterIndex.get(ids[0]);
					int cluster_index2 = articles_clusterIndex.get(ids[1]);
					if(Positive){
						if(cluster_index1 == cluster_index2)
							count[0]++; // TP
						else
							count[1]++; //FN
					}
					else{
						if(cluster_index1 == cluster_index2)
							count[1]++; // FP
						else
							count[0]++; //TN
					}
					
				}
				line = br.readLine();
			}
			br.close();
		}catch(IOException e)
		{
			e.printStackTrace();
		}catch(Exception e)
		{
			e.printStackTrace();
		}
		return count;
	}
	
	public int[] GetCountfromClusters(String filename){
		int count[] = new int[4]; // TP, FN, TN, FP
		File f=new File(filename);
		FileInputStream fis;
		ArrayList<ArrayList<String>> gold_clusters = new ArrayList<ArrayList<String>>();
		try {
			fis = new FileInputStream(f);
			InputStreamReader isr=new InputStreamReader(fis);
			BufferedReader br=new BufferedReader(isr);
			String line = br.readLine();
			while(line != null){
				line = line.trim();
				if(line.length()>0){
					String s[] = line.split("\t");
					ArrayList<String> gold_cluster = new ArrayList<String>(Arrays.asList(s));
					gold_cluster.remove(0);
					gold_clusters.add(gold_cluster);
				}
				line = br.readLine();
			}
			br.close();
			for(ArrayList<String> gold_cluster: gold_clusters){
				for(int i=0; i<gold_cluster.size(); i++){
					if(!articles_clusterIndex.containsKey(gold_cluster.get(i)))
						continue;
					int cluster_index1 = articles_clusterIndex.get(gold_cluster.get(i));
					for(int j=i+1; j<gold_cluster.size(); j++){
						if(!articles_clusterIndex.containsKey(gold_cluster.get(j)))
							continue;
						int cluster_index2 = articles_clusterIndex.get(gold_cluster.get(j));
						if(cluster_index1 == cluster_index2)
							count[0]++;
						else
							count[1]++;
					}
				}	
			}
			for(int i=0; i<gold_clusters.size(); i++)
				for(int j=i+1; j<gold_clusters.size(); j++){
					for(String pmid1: gold_clusters.get(i)){
						if(!articles_clusterIndex.containsKey(pmid1))
							continue;
						int index1 = articles_clusterIndex.get(pmid1);
						for(String pmid2: gold_clusters.get(j)){
							if(!articles_clusterIndex.containsKey(pmid2))
								continue;
							int index2 = articles_clusterIndex.get(pmid2);
							if(index1 == index2)
								count[3]++;
							else
								count[2]++;
						}
					}
				}
		}catch(IOException e)
		{
			e.printStackTrace();
		}catch(Exception e)
		{
			e.printStackTrace();
		}
		return count;
	}
}
